﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="ExtraObject.cs" company="">
//   
// </copyright>
// <summary>
// A general object.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

/*
 * Author: Barbara Carboni
 * Created: 17-11-2011
 * Review: 01-12-2011
 */

namespace ITU_vs_Zombies.Stuff
{
    using System;
    using System.Diagnostics.Contracts;

    using ITU_vs_Zombies.Game;
    using ITU_vs_Zombies.Graphics;

    using Microsoft.Xna.Framework;
    using Microsoft.Xna.Framework.Audio;
    using Microsoft.Xna.Framework.Graphics;

    /// <summary>
    /// A general object.
    /// </summary>
    [Serializable]
    public abstract class ExtraObject : ICloneable
    {
        #region Constants and Fields

        /// <summary>
        /// The Image.
        /// </summary>
        public readonly string Image;

        /// <summary>
        /// Gets or sets sound.
        /// </summary>
        [NonSerialized]
        public SoundEffect Sound;

        /// <summary>
        /// The texture.
        /// </summary>
        [NonSerialized]
        public Texture2D Texture;

        /// <summary>
        /// The number of Frames in the Image.
        /// </summary>
        protected readonly uint NumberFrames;

        #endregion

        #region Constructors and Destructors

        /// <summary>
        /// Initializes a new instance of the <see cref="ExtraObject"/> class. 
        /// </summary>
        /// <param name="image">
        /// The Image. 
        /// </param>
        /// <param name="numberFrames">
        /// The number of Frames in the Image.
        /// </param>
        /// <param name="numberFloor">
        /// The position in the space where it is. 
        /// </param>
        /// <param name="position">
        /// The position.
        /// </param>
        /// <param name="sound">
        /// The sound.
        /// </param>
        public ExtraObject(string image, uint numberFrames, int numberFloor, Vector2 position, string sound)
        {
            Contract.Requires(image != null);
            Contract.Requires(sound != null);
            Contract.Requires(numberFrames > 0);

            // TODO: check that the parameter 'number of floor' is between 0 and the max no. of floor (put something in the class 'floor') 
            // Contract.Requires(NumberFloor>=0&&NumberFrames<5);
            Contract.Requires(position.X >= 0 && position.Y >= 0);
            this.Image = image;
            this.NumberFrames = numberFrames;
            this.NumberFloor = numberFloor;
            this.Position = position;
            this.Animation = new Animation();
            this.StringSound = sound;
        }

        #endregion

        #region Public Properties

        /// <summary>
        /// Gets Animation.
        /// </summary>
        public Animation Animation { get; private set; }

        /// <summary>
        /// Gets or sets the number of the Floor where it is.
        /// </summary>
        public int NumberFloor { get; set; }

        /// <summary>
        /// Gets or sets Position.
        /// </summary>
        public Vector2 Position { get; set; }

        /// <summary>
        /// Gets or sets StringSound.
        /// </summary>
        public string StringSound { get; set; }

        #endregion

        #region Public Methods

        /// <summary>
        /// The clone.
        /// </summary>
        /// <returns>
        /// The clone.
        /// </returns>
        public virtual object Clone()
        {
            var extraObject = (ExtraObject)this.MemberwiseClone();
            extraObject.StringSound = this.StringSound;
            extraObject.Animation = new Animation();
            var texture2D = Client.Content.Load<Texture2D>(this.Image);
            extraObject.Animation.Initialize(
                texture2D, this.Position, (int)this.NumberFrames, Color.White, 1f, true, false);
            return extraObject;
        }

        /// <summary>
        /// The dispose.
        /// </summary>
        public void Dispose()
        {
            this.Animation.Dispose();
        }

        /// <summary>
        /// The draw.
        /// </summary>
        /// <param name="spriteBatch">
        /// The sprite batch. 
        /// </param>
        public void Draw(SpriteBatch spriteBatch)
        {
            Contract.Requires(spriteBatch != null);
            this.Animation.Draw(spriteBatch);
        }

        /// <summary>
        /// The load content.
        /// </summary>
        public void LoadContent()
        {
            Contract.Requires(Client.Content != null);
            Contract.Requires(Client.GraphicsDevice != null);
            this.Texture = Client.Content.Load<Texture2D>(this.Image);
            this.Position = new Vector2(this.Position.X, this.Position.Y - this.Texture.Height);
            this.Sound = Client.Content.Load<SoundEffect>(this.StringSound);
            this.Animation.Initialize(this.Texture, Vector2.Zero, (int)this.NumberFrames, Color.White, 1f, true, false);
        }

        /// <summary>
        /// The update.
        /// </summary>
        /// <param name="gameTime">
        /// The game time. 
        /// </param>
        /// <param name="position">
        /// The position. 
        /// </param>
        public virtual void Update(GameTime gameTime, Vector2 position)
        {
            Contract.Requires(gameTime != null);
            this.Animation.Position = new Vector2(this.Position.X - Math.Abs(position.X), this.Position.Y);
            this.Animation.Update(gameTime);
        }

        #endregion
    }
}